﻿using System;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Security.Permissions;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using Org.Eurekaa.DNJ.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Drawing.Design;



using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Org.Eurekaa.DNJ.UI.Common;
using System.Text.RegularExpressions;
using Org.Eurekaa.DNJ.Collections;


namespace Org.Eurekaa.DNJ.UI.Design.WebControls
{    
    [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    abstract class DNJMultiboxControlDesigner : JQueryUIControlDesigner
    {
        private string HEADER_PREFIX = "Header";
        private string CONTENT_PREFIX = "Content";
        private DNJMultiboxControl multiboxControl;

        public DNJMultiboxControl MultiboxControl
        {
            get { return multiboxControl; }
        }

        #region implementations
        public override void Initialize(IComponent component)
        {
            // Initialize the base
            base.Initialize(component);
            multiboxControl = (DNJMultiboxControl)component;
            HEADER_PREFIX += multiboxControl.ID;
            CONTENT_PREFIX += multiboxControl.ID;
        }

        public override bool AllowResize
        {
            get
            {
                return true;
            }
        }

        public override String GetDesignTimeHtml(DesignerRegionCollection regions)
        {

            //add design regions for all header cells, the region name will be prefixd with 
            // HEADER_PREFIX, and extended with the tab page index. 
            for (int i = 0; i < multiboxControl.BoxList.Count; i++)
            {
                regions.Add(new DesignerRegion(this, HEADER_PREFIX + i.ToString()));
            }

            // Create an editable region and add it to the regions
            // the design region name will take CONTENT_PREFIX as prefix and the index
            // of the current active tab.

            EditableDesignerRegion editableRegion =
                new EditableDesignerRegion(this,
                    CONTENT_PREFIX + multiboxControl.CurrentDesignBox, false);
            regions.Add(editableRegion);

            // Set the highlight for the selected region
            regions[multiboxControl.CurrentDesignBox].Highlight = true;

            // Use the base class to render the markup
            string str = base.GetDesignTimeHtml();
            return base.GetDesignTimeHtml();
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
        }
        protected override void OnClick(DesignerRegionMouseEventArgs e)
        {
            if (e.Region == null)
                return;

            // If the clicked region is not a header, return
            if (e.Region.Name.IndexOf(HEADER_PREFIX) != 0)
                return;

            // Switch the current view if required
            //only when the clicked region is different than the active region.
            if (e.Region.Name.Substring(HEADER_PREFIX.Length) != multiboxControl.CurrentDesignBox.ToString())
            {
                //extract the index of the design region, and set the CurrentDesignTab index
                multiboxControl.CurrentDesignBox = int.Parse(e.Region.Name.Substring(HEADER_PREFIX.Length));
                
                //then after update the design time HTML
                base.UpdateDesignTimeHtml();
            }
        }


        public override string GetEditableDesignerRegionContent(EditableDesignerRegion region)
        {
            // Get a reference to the designer host
            IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));

            //only if known host, and we have some TabPages
            if (host != null && multiboxControl.BoxList.Count > 0)
            {
                //we need to get the contents of the TabBody of the tabControl

                ITemplate template = multiboxControl.BoxList[0].Content;


                if (region.Name.StartsWith(CONTENT_PREFIX))
                {
                    //get the template of the selected tab

                    //extract the tab index of the edited region, from the region name.
                    int tabIndex = int.Parse(region.Name.Substring(CONTENT_PREFIX.Length));

                    //switch the design template to the selected tab index.
                    template = multiboxControl.BoxList[tabIndex].Content;
                }

                // Persist the template in the design host
                if (template != null)
                    return ControlPersister.PersistTemplate(template, host);
            }

            return String.Empty;
        }

        public override void SetEditableDesignerRegionContent(EditableDesignerRegion region, string content)
        {
            if (content == null)
                return;


            // Get a reference to the designer host
            IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));
            if (host != null)
            {
                // Create a template from the content string
                ITemplate template = ControlParser.ParseTemplate(host, content);

                if (template != null)
                {
                    // Determine which region should get the template
                    if (region.Name.StartsWith(CONTENT_PREFIX))
                    {
                        int tabIndex = int.Parse(region.Name.Substring(CONTENT_PREFIX.Length));
                        //set back the template for the selected tab body
                        multiboxControl.BoxList[tabIndex].Content = template;
                    }
                }
            }
        }


        #endregion implementations



        // Create a custom ActionLists collection
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                // Create the collection
                DesignerActionListCollection actionLists = new DesignerActionListCollection();

                // Get the base items, if any
                actionLists.AddRange(base.ActionLists);

                // Add a custom list of actions
                actionLists.Add(new DNJMultiboxActionList(this));

                return actionLists;

            }
        }


        //The author of this method (StartTabCollectionEditor) is Sike Mullivan(http://www.codeproject.com/Members/Skully1022)
        //Licence : The Code Project Open License (CPOL) 1.02 (http://www.codeproject.com/info/cpol10.aspx)
        public void StartTabCollectionEditor()
        {
            IDesignerHost service = (IDesignerHost)this.GetService(typeof(IDesignerHost));
            PropertyDescriptor propDesc = TypeDescriptor.GetProperties(base.Component)["BoxList"];
            object val = propDesc.GetValue(multiboxControl);

            using (DesignerTransaction transaction = service.CreateTransaction("Start Pages Collection Editor"))
            {
                UITypeEditor editor = (UITypeEditor)propDesc.GetEditor(typeof(UITypeEditor));

                DNJGenericCollection<DNJBox> result = (DNJGenericCollection<DNJBox>)editor.EditValue(new TypeDescriptorContext(service, propDesc, base.Component),
                    new WindowsFormsEditorServiceHelper(this), val);
                
                if (result != null)
                {                    
                    transaction.Commit();
                }
            }
        }    
    
    
    }




    // Create an embedded DesignerActionList class
    class DNJMultiboxActionList : DesignerActionList
    {
        // Create private fields
        private DNJMultiboxControlDesigner _parent;
        private DesignerActionItemCollection items;

        // Constructor
        public DNJMultiboxActionList(DNJMultiboxControlDesigner parent)
            : base(parent.Component)
        {
            _parent = parent;
        }

        // Create a set of transacted callback methods
        // Callback for the wide format
        public void EditTabPages()
        {
            try
            {
                this._parent.StartTabCollectionEditor();
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString(), "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        public void CreateTabPage()
        {
            DNJMultiboxControl tabView = (DNJMultiboxControl)_parent.Component;


            // Create the callback
            TransactedChangeCallback toCall = new TransactedChangeCallback(AddTabPage);
            // Create the transacted change in the control
            ControlDesigner.InvokeTransactedChange(tabView, toCall, null, "Add new Page");
        }
        // Get the sorted list of Action items
        public override DesignerActionItemCollection GetSortedActionItems()
        {
            if (items == null)
            {
                // Create the collection
                items = new DesignerActionItemCollection();

                // Add Tab Page command
                items.Add(new DesignerActionMethodItem(this, "CreateTabPage", "Add new Page", true));
                items.Add(new DesignerActionMethodItem(this, "EditTabPages", "Add/Remove/Edit Pages", true));
            }
            return items;
        }

        // Function for the callbacks to call
        public bool AddTabPage(object arg)
        {
            // Get a reference to the designer's associated component
            DNJMultiboxControl tabsView = (DNJMultiboxControl)_parent.Component;

            DNJBox tp = new DNJBox();
            tp.ID = "Box" + tabsView.BoxList.Count.ToString();
            tp.Title = "Box" + tabsView.BoxList.Count.ToString();
            tabsView.BoxList.Add(tp);            
            _parent.UpdateDesignTimeHtml();

            // Return an indication of success
            return true;
        }
    }

}
